package com.zbkj.client.task;

import com.alibaba.fastjson.JSON;
import com.zbkj.client.config.WebSocketSessionManager;
import com.zbkj.client.enums.WebSocketEventType;
import com.zbkj.client.service.ClientLoginService;
import com.zbkj.common.model.client.digital.CustomDigitalPerson;
import com.zbkj.client.vo.CustomDpCjVo;
import com.zbkj.service.service.CustomDigitalPersonService;
import com.zbkj.client.service.DigitalPersonService;
import io.reactivex.rxjava3.core.Single;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Slf4j
@Component
public class CustomDpStatusUpdateTask {

    @Resource
    private ThreadPoolTaskScheduler taskScheduler;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private CustomDigitalPersonService customDigitalPersonService;
    @Resource
    private DigitalPersonService digitalPersonService;

    @Autowired
    private WebSocketSessionManager webSocketSessionManager;


    @Autowired
    private ClientLoginService clientLoginService;

    @Value("${digital-person.url}")
    private String digitalPersonUrl;

    private final String customDpDetailUrl = "/open/v1/customised_person";
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Autowired
    private CustomDpUrlUpdateTask customDpUrlUpdateTask;

    /**
     * 启动定时任务
     * @param linkId 蝉镜返回的id
     */
    public void start(String linkId) {
        schedule(linkId, 0);
    }

    private void schedule(String linkId, int retryCount) {
        long delay = retryCount == 0 ? 3 * 60 * 1000 : 60 * 1000; // 首次3分钟，后续1分钟
//        long delay = retryCount == 0 ? 1000 : 60 * 1000; // 测试的时候设置1秒
        taskScheduler.schedule(() -> {
            try {
                doTask(linkId, retryCount);
            } catch (Exception e) {
                log.error("定时任务-定制数字人定时任务异常", e);
            }
        }, new Date(System.currentTimeMillis() + delay));
    }

    private void doTask(String linkId, int retryCount) {
        CustomDigitalPerson digitalPerson = customDigitalPersonService.lambdaQuery()
                .eq(CustomDigitalPerson::getLinkId, linkId)
                .one();
        if (digitalPerson == null) {
            log.warn("定时任务-未找到定制数字人记录，linkId={}", linkId);
            return;
        }
        if (digitalPerson.getIsDel() != null && digitalPerson.getIsDel() == 1) {
            log.info("定制数字人已被删除，linkId={}", linkId);
            return;
        }
        if (digitalPerson.getStatus() != null && digitalPerson.getStatus() != 1) {
            log.info("定时任务-定制数字人已更新过，linkId={}", linkId);
            return;
        }

        // 拉取蝉镜接口
        String accessToken = digitalPersonService.getAccessToken();
        String url = digitalPersonUrl + customDpDetailUrl + "?id=" + linkId;
        HttpHeaders headers = new HttpHeaders();
        headers.set("access_token", accessToken);
        HttpEntity<Void> entity = new HttpEntity<>(headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        String body = response.getBody();
        if (body == null) {
            log.warn("蝉镜返回空数据，linkId={}", linkId);
            return;
        }
        try {
            JsonNode root = objectMapper.readTree(body);
            int code = root.path("code").asInt();
            if (code != 0) {
                log.warn("蝉镜返回code!=0，linkId={}, code={}, msg={}", linkId, code, root.path("msg").asText());
                schedule(linkId, retryCount + 1);
                return;
            }
            JsonNode dataNode = root.path("data");
            if (dataNode.isMissingNode() || dataNode.isNull()) {
                log.warn("蝉镜返回data字段为空，linkId={}", linkId);
                return;
            }
            CustomDpCjVo cjVo = objectMapper.treeToValue(dataNode, CustomDpCjVo.class);
            if (cjVo == null) {
                log.warn("data字段转CustomDpCjVo失败，linkId={}", linkId);
                return;
            }

            if (cjVo.getStatus() != 1 && digitalPerson.getStatus() == 1) {
                // 需要更新
                // 原有字段更新逻辑
                digitalPerson.setName(cjVo.getName());
                digitalPerson.setType(cjVo.getType());
                digitalPerson.setPicUrl(cjVo.getPic_url());
                digitalPerson.setPreviewUrl(cjVo.getPreview_url());
                digitalPerson.setWidth(cjVo.getWidth());
                digitalPerson.setHeight(cjVo.getHeight());
                digitalPerson.setAudioManId(cjVo.getAudio_man_id());
                digitalPerson.setStatus(cjVo.getStatus());
                digitalPerson.setErrReason(cjVo.getErr_reason());
                digitalPerson.setIsOpen(cjVo.getIs_open());
                digitalPerson.setReason(cjVo.getReason());
                digitalPerson.setProgress(cjVo.getProgress());
                digitalPerson.setUpdateTime(new Date());

                customDigitalPersonService.updateById(digitalPerson);

                // 2. 事件名判断
                String eventName;
                //推送ws
                if (cjVo.getStatus() != null && cjVo.getStatus() == 2) {
                    eventName = WebSocketEventType.AddCustomDpSuccess.name();
                    // 异步上传OSS和更新数据库
                    customDpUrlUpdateTask.start(digitalPerson, cjVo);
                } else {
                    //设置推送到ws事件的名
//                    eventName = "AddCustomDpFail";
                    eventName = WebSocketEventType.AddCustomDpFail.name();
                }

                // 3. WebSocket事件推送
                Integer userId = digitalPerson.getUserId();
                if (userId != null) {
                    Map<String, Object> data = new HashMap<>();
                    data.put("id", digitalPerson.getId());
                    data.put("linkId", cjVo.getId());
                    data.put("status", cjVo.getStatus());

                    Map<String, Object> message = new HashMap<>();
                    message.put("event", eventName);
                    message.put("data", data);

                    String jsonMessage = JSON.toJSONString(message);
                    webSocketSessionManager.sendMessageToUser(userId, jsonMessage);
                    log.info("向用户 {} 推送定制数字人状态更新: {}", userId, jsonMessage);
                }

                log.info("定时任务-定制数字人状态已更新，linkId={}", linkId);
                return;
            }

            if (cjVo.getStatus() == 1 && digitalPerson.getStatus() == 1 && retryCount < 5) {
                log.info("定制数字人未完成，1分钟后重试，linkId={}, retry={}", linkId, retryCount + 1);
                schedule(linkId, retryCount + 1);
            }
        } catch (Exception e) {
            log.error("解析蝉镜返回数据异常，linkId={}", linkId, e);
        }
    }
}
